import viewmode from "./viewmode.mjs";
import render_helper from "./render_helper.mjs";
import datarover from "./datarover.mjs";
import thin_render from "./thin_render.mjs";
import thin_rerender from "./thin_rerender.mjs";
import collectdata from "./collectdata.mjs";
import {
  nearest_querycontainer,
  nearest_data,
  nearest_render,
  nearest_param,
} from "./nearest.mjs";
import validate from "./validate.mjs";
import thin_ajax from "./thin_ajax.mjs";
import render_content from "./render_content.mjs";
import { confirm, dialog } from "./dialog.mjs";
import { thin } from "../thin3.mjs";
import { after } from "./delay_render.mjs";

export default function (container, template) {
  let mode = viewmode(container) === "read" ? "read" : "edit";
  // console.log({ viewmode: viewmode(container), mode });
  let gridview = document.createElement("gridview");
  container.appendChild(gridview);
  gridview.thin_render = render;
  gridview.thin_render();

  function render() {
    let override = {};
    if (template.height === "auto") {
      override.height = undefined;
      override.height = `calc(100% - ${gridview.offsetTop}px)`;
      after(function () {
        let parent = gridview.offsetParent;
        let bottom = parent
          ? parent.scrollHeight - gridview.offsetTop - gridview.offsetHeight
          : 0;
        // console.log({
        //   offsetHeight: parent.offsetHeight,
        //   scrollHeight: parent.scrollHeight,
        //   top: gridview.offsetTop,
        //   height: gridview.offsetHeight,
        //   bottom,
        //   css: `calc(100% - ${gridview.offsetTop + bottom}px)`,
        // });
        gridview.style = `height: calc(100% - ${
          gridview.offsetTop + bottom
        }px)`;
      });
    }
    render_helper(gridview, { ...template, ...override });

    let table = document.createElement("table");
    gridview.appendChild(table);

    if (template.data) table.thin_data = template.data;

    let colgroup = document.createElement("colgroup");
    table.appendChild(colgroup);

    let thead = document.createElement("thead");
    table.appendChild(thead);
    let headerrow = document.createElement("tr");
    thead.appendChild(headerrow);

    // 渲染表头
    template.gridview?.forEach((col) => {
      let co = document.createElement("col");
      render_helper(co, col);
      colgroup.appendChild(co);
      let th = document.createElement("th");
      if (col.width) th.style.width = col.width;
      if (typeof col.title !== "undefined") {
        thin_render(th, col.title);
      } else if (typeof col.col === "string") {
        thin_render(th, col.col);
      }
      headerrow.appendChild(th);
      if (col.class) {
        th.setAttribute("class", col.class);
      }
    });

    // 渲染过滤器
    if (
      template.gridview?.find((col) => {
        return col.filter !== undefined;
      })
    ) {
      let filterrow = document.createElement("tr");
      thead.appendChild(filterrow);

      template.gridview.forEach((col) => {
        let td = document.createElement("td");
        filterrow.appendChild(td);
        if (col.class) {
          td.setAttribute("class", col.class);
        }

        if (col.filter === undefined) {
        } else if (col.filter.input) {
          thin_render(td, {
            input: col.filter.input,
            type: col.filter.type,
            value: "[[filter/" + col.filter.input + "]]",
            event: { change: col.filter.event?.change || filter_handler },
          });
        } else if (col.filter.select) {
          if (col.filter.datapath) {
            let options =
              col.filter.emptyforall === true
                ? [""].concat(datarover(td, col.filter.datapath))
                : datarover(td, col.filter.datapath);
            thin_render(td, {
              select: col.filter.select,
              value: "[[filter/" + col.filter.select + "]]",
              options: options,
              event: { change: col.filter.event?.change || filter_handler },
            });
          } else if (col.filter.ajax) {
            thin_render(td, {
              select: col.filter.select,
              value: "[[filter/" + col.filter.select + "]]",
              ajax: col.filter.ajax,
              event: { change: col.filter.event?.change || filter_handler },
            });
          } else {
            thin_render(td, {
              select: col.filter.select,
              value: "[[filter/" + col.filter.select + "]]",
              options: col.filter.options,
              event: { change: col.filter.event?.change || filter_handler },
            });
          }
        } else {
          thin_render(td, col.filter);
          td.addEventListener("change", (ev) => {
            console.log(ev);
            if (ev.target.classList.contains("selectall")) {
              // filter_handler({ sender: ev.target, event: ev });
            } else {
              filter_handler({ sender: ev.target, event: ev });
            }
          });
        }
      });
      //filter事件

      function filter_handler(ev) {
        let filter = {};
        let d = collectdata(filterrow);
        for (let key in d) {
          // console.log(key);
          if (d[key] !== "") {
            filter[key] = d[key];
          }
        }

        if (template.onfilter) {
          template.onfilter({ filter: filter });
        } else {
          let querycontainer = nearest_querycontainer(ev.sender);
          console.log({ ev: ev, querycontainer: querycontainer, filter });
          querycontainer.thin_query.filter = filter;
          querycontainer.thin_query.pagenum = 1;
          thin_rerender(querycontainer);
        }
      }
    }

    // 渲染表体
    if (template.groupdatapath) {
      let groups = datarover(container, template.groupdatapath);
      groups?.forEach((group) => {
        let tbody = document.createElement("tbody");
        table.appendChild(tbody);
        tbody.thin_data = group;

        if (template.grouprowtemplate) {
          let tr = document.createElement("tr");
          tbody.appendChild(tr);
          if (typeof template.grouprowtemplate === "object") {
          } else if (typeof template.grouprowtemplate === "string") {
            thin_render(tr, {
              td: template.grouprowtemplate,
              class: "fixed",
              a: {
                // colspan: template.gridview.length,
                colspan: 3,
                // class: "fixed",
              },
            });
          }
        }
        row_group(tbody, datarover(group, template.datapath));
      });
    } else {
      let tbody = document.createElement("tbody");
      table.appendChild(tbody);

      let data = template.data || datarover(container, template.datapath);

      if (!data && template.datapath) {
        data = [];
        datarover(container, template.datapath, data);
      }

      row_group(tbody, data);
    }

    function row_group(tbody, data) {
      // 拖拽排序支持
      if (template.rowdrag) {
        // console.log("rowdrag");
        tbody.ondragstart = (e) => {
          console.log(e);
          let tr = e.target;
          let receiver = e.target.closest("tbody");
          let controller = new AbortController();
          receiver.addEventListener(
            "dragover",
            (e) => {
              e.preventDefault();
            },
            { signal: controller.signal }
          );
          receiver.addEventListener(
            "drop",
            (e) => {
              // console.log(e);
              let target = e.target.closest("tr");
              receiver.insertBefore(tr, target.nextSibling);
              controller.abort();
              let result = [];
              receiver.querySelectorAll("tr").forEach((tr) => {
                if (tr.thin_data && tr.thin_rowindex !== undefined) {
                  result.push(tr.thin_data);
                }
              });
              template.rowdrag(result);
            },
            { signal: controller.signal }
          );
        };
      }

      // 数据行
      if (Array.isArray(data)) {
        tbody.thin_rowdata = data;
        let rowindex = 0;
        data.forEach((row) => {
          let tr = document.createElement("tr");
          tr.thin_data = row;
          tr.thin_rowindex = rowindex;
          tbody.appendChild(tr);

          if (template.rowdrag) tr.setAttribute("draggable", true);

          if (template.rowclass) {
            if (typeof template.rowclass === "function") {
              tr.classList.add(template.rowclass(row));
            } else {
              tr.classList.add(template.rowclass);
            }
          }

          row_render({ tr, row });

          rowindex++;
        });
      }

      if (template.rowinsert && mode === "edit") {
        let tr = document.createElement("tr");
        tbody.appendChild(tr);
        tr.setAttribute("insertrow", true);
        tr.thin_data = { ...template.rowinsert_defaultvalue } || {};
        row_render({
          tr,
          insert: true,
        });
      }

      function row_render({ tr, row, insert }) {
        if (template.debug) console.log(row);

        template.gridview?.forEach((col) => {
          let td = document.createElement("td");
          tr.appendChild(td);
          // class
          if (typeof col.class === "function") {
            let _class = col.class(row);
            _class?.split(" ").forEach((c) => {
              td.classList.add(c);
            });
          } else if (col.class) {
            col.class?.split(" ").forEach((c) => {
              td.classList.add(c);
            });
          }

          if (template.rowedit && mode === "edit") {
            if (/\[\[[\w/.]+\]\]/.test(col.col)) normal_col();
            else if (col.readonly && !insert) normal_col();
            else edit_col();
          } else normal_col();

          function normal_col() {
            if (col.click) render_helper(td, { click: col.click });
            // console.log(col);
            if (/\[\[[\w/.]+\]\]/.test(col.col)) {
              thin_render(td, col.col);
            } else if (
              typeof col.col === "object" ||
              typeof col.col === "function"
            ) {
              thin_render(td, col.col);
            } else if (col.NumberFormat) {
              let d = datarover(td, col.col);
              // console.log(d);
              if (!d && d !== 0) {
              } else if (Number.isNaN(d)) {
                td.innerText = d;
              } else {
                let options = {};
                for (let key in col.NumberFormat) {
                  // console.log(key);
                  if (typeof col.NumberFormat[key] === "string") {
                    options[key] = render_content(td, col.NumberFormat[key]);
                  } else {
                    options[key] = col.NumberFormat[key];
                  }
                }
                td.innerText = new Intl.NumberFormat(
                  "en-US",
                  // col.NumberFormat
                  options
                ).format(d);
              }
              bindrowclick();
            } else if (col.DateTimeFormat) {
              // console.log({ normal_col_datetimeformat: col.DateTimeFormat });
              let d = datarover(td, col.col);
              d = d?.replace(/\//g, "-");
              let t = new Date(`${d}`);
              // let t = Date.parse(`${d} GMT`);
              // let t = Date.UTC(d);
              // console.log({ d, t });
              if (!isNaN(t.getTime())) {
                t = Date.UTC(
                  t.getFullYear(),
                  t.getMonth(),
                  t.getDate(),
                  t.getHours(),
                  t.getMinutes(),
                  t.getSeconds(),
                  t.getMilliseconds()
                );
                td.innerText = new Intl.DateTimeFormat(
                  "default",
                  // "en-US",
                  col.DateTimeFormat
                ).format(t);
              } else {
              }
              bindrowclick();
            } else if (typeof col.col === "string") {
              if (col.ajax?.display) {
                let q = {};
                q[col.ajax.value] = datarover(td, col.col);
                // console.log(q);
                thin_ajax({
                  type: "get",
                  url: col.ajax.url,
                  data: { ...col.ajax.query, ...q },
                  success: (data) => {
                    // console.log(data);
                    let d = datarover(data, col.ajax.datapath);
                    // console.log({ d });
                    if (d === undefined) {
                      thin_render(td, col.col);
                    } else if (Array.isArray(d) && d.length === 1) {
                      thin_render(td, render_content(d[0], col.ajax.display));
                    } else {
                      thin_render(td, `[[${col.col}]]`);
                    }
                  },
                });
              } else if (col.ajax?.param) {
                let query = {};
                query[col.ajax.param] = datarover(td, col.col);
                // console.log({ query });
                thin
                  .ajax({
                    url: col.ajax.url,
                    type: "get",
                    data: { ...col.ajax.query, ...query },
                  })
                  .done((data) => {
                    let rows = datarover(data, col.ajax.datapath);
                    // console.log({ data, rows });
                    if (rows.length === 1) {
                      thin_render(td, render_content(rows[0], col.ajax.text));
                    } else {
                      thin_render(td, `[[${col.col}]]`);
                    }
                  });
              } else if (col.type === "datetime") {
              } else if (col.col) {
                thin_render(td, `[[${col.col}]]`);
              }
              bindrowclick();
            } else {
              console.log({ col });
            }

            function bindrowclick() {
              if (template.rowclick)
                render_helper(td, {
                  click: (e) => {
                    savescrollpos();
                    template.rowclick(e);
                  },
                });
            }
          }

          function edit_col() {
            if (typeof col.col === "object") {
              thin_render(td, col.col);
            } else if (typeof col.col === "function") {
              col.col({ container: td, data: nearest_data(td) });
            } else if (col.type === "checkbox" || col.type === "select") {
              thin_render(td, {
                input: col.col,
                id: col.col,
                type: col.type,
                bind: col.col,
                options: col.options,
                watch: col.watch,
                ajax: col.ajax,
                a: col.a,
                event: {
                  change: (e) => {
                    if (template.rowchange && !insert) {
                      template.rowchange(e);
                      template?.changed?.(e);
                    }
                    if (template.insertrowchange && insert)
                      template.insertrowchange(e);
                  },
                },
              });
            } else if (col.type === "textarea") {
              thin_render(td, {
                textarea: col.col,
                id: col.col,
                bind: col.col,
                a: col.a,
                event: {
                  // load: (e) => {
                  //   e.sender.style.height = "0px";
                  //   e.sender.style.height = `${e.sender.scrollHeight}px`;
                  // },
                  change: (e) => {
                    if (template.rowchange && !insert) template.rowchange(e);
                    if (template.insertrowchange && insert)
                      template.insertrowchange(e);
                  },
                  input: (e) => {
                    e.sender.style.height = "0px";
                    e.sender.style.height = `${e.sender.scrollHeight}px`;
                  },
                },
              });
              let ele = td.querySelector("textarea");
              ele.style.height = "0px";
              ele.style.height = `${ele.scrollHeight}px`;
            } else if (
              insert ||
              (!col.DateTimeFormat && !col.NumberFormat && !col.underline)
            ) {
              switch (col.type) {
                default:
                  let t = {
                    input: col.col,
                    id: col.col,
                    type: col.type,
                    ajax: col.ajax,
                    options: col.options,
                    a: col.a,
                    event: {
                      change: (e) => {
                        if (template.rowchange && !insert)
                          template.rowchange(e);
                        if (template.insertrowchange && insert)
                          template.insertrowchange(e);
                      },
                    },
                  };
                  if (col.col) t.bind = col.col;
                  thin_render(td, t);
                  break;
              }
            } else {
              let underline = document.createElement("underline");
              td.appendChild(underline);
              render_value();

              function render_value() {
                switch (typeof col.col) {
                  case "string":
                    let value = datarover(td, col.col);
                    if (!value && value !== 0) {
                    } else if (col.NumberFormat) {
                      underline.innerText = new Intl.NumberFormat(
                        "en-US",
                        col.NumberFormat
                      ).format(value);
                    } else if (col.DateTimeFormat) {
                      // console.log({
                      //   edit_col_datetimeformat: col.DateTimeFormat,
                      // });
                      value = value?.replace(/\//g, "-");
                      value = new Date(`${value}`);
                      if (!isNaN(value.getTime())) {
                        value = Date.UTC(
                          value.getFullYear(),
                          value.getMonth(),
                          value.getDate(),
                          value.getHours(),
                          value.getMinutes(),
                          value.getSeconds(),
                          value.getMilliseconds()
                        );
                        underline.innerText = new Intl.DateTimeFormat(
                          "default",
                          col.DateTimeFormat
                        ).format(value);
                      } else {
                        underline.innerText = value;
                      }
                    } else underline.innerText = value;
                    break;
                }
              }

              underline.onclick = (e) => {
                console.log(e);
                if (typeof col.edit === "function") {
                  col.edit({
                    element: td,
                    data: nearest_data(td),
                    done: function () {
                      render_value();
                    },
                    changed: function (result) {
                      Object.assign(nearest_data(td), result);
                      if (template.rowchange)
                        template.rowchange({
                          new_data: {},
                          org_data: nearest_data(td),
                        });
                      render_value();
                    },
                  });
                } else {
                  let t;
                  if (typeof col.edit === "object") {
                    t = col.edit;
                  } else {
                    switch (col.type) {
                      default:
                        t = [
                          { div: `${col.col}:` },
                          {
                            input: col.col,
                            id: col.col,
                            value: `[[${col.col}]]`,
                            type: col.type,
                            ajax: col.ajax,
                            a: col.a,
                          },
                          "<br/>",
                          "<br/>",
                        ];
                    }
                  }
                  confirm(t, nearest_data(td)).confirmed((result) => {
                    console.log(result);
                    Object.assign(nearest_data(td), result);
                    if (template.rowchange)
                      template.rowchange({
                        new_data: {},
                        org_data: nearest_data(td),
                      });
                    if (col.changed)
                      col.changed({
                        new_data: result,
                        org_data: nearest_data(td),
                      });
                    render_value();
                  });
                }
              };
            }
          }
        });

        if ((template.rowinsert || template.rowdelete) && mode === "edit") {
          let td = document.createElement("td");
          tr.appendChild(td);
          if (!insert && template.rowdelete) {
            thin_render(td, {
              button: "delete",
              click: (e) => {
                console.log({ delete: e, template });
                if (typeof template.rowdelete === "function") {
                  template.rowdelete(e, do_delete);
                } else if (template.rowdelete === true) {
                  do_delete();
                  // console.log(e);
                  // // let d = nearest_data(tbody);
                  // let d = tbody.thin_rowdata;
                  // d.splice(e.rowindex, 1);
                  // thin(tbody).empty();
                  // row_group(tbody, d);
                }

                function do_delete() {
                  console.log(e);
                  // let d = nearest_data(tbody);
                  let d = tbody.thin_rowdata;
                  d.splice(e.rowindex, 1);
                  thin(tbody).empty();
                  row_group(tbody, d);
                }
                template?.deleted?.(e);
              },
            });
          }
          if (insert) {
            thin_render(td, {
              button: "insert",
              click: async (e) => {
                console.log({ e, template });

                await template?.beforeinsert?.(e);
                // await new Promise((resolve, reject) => {});
                if (typeof template.rowinsert === "function") {
                  console.log(1);
                  validate({
                    container: tr,
                    valid: async () => {
                      await template.rowinsert(e, do_insert);
                      console.log(2);
                    },
                    invalid: () => {
                      e.done();
                    },
                  });
                  console.log(3);
                } else if (template.rowinsert === true) {
                  do_insert();
                  // // let d = nearest_data(tbody);
                  // let d = tbody.thin_rowdata;
                  // console.log(d);
                  // validate({
                  //   container: tr,
                  //   valid: function () {
                  //     // console.log({ e, d });
                  //     d.push({ ...e.new_data, ...e.org_data });
                  //     thin(tbody).empty();
                  //     row_group(tbody, d);
                  //   },
                  //   invalid: function () {
                  //     e.done();
                  //   },
                  // });
                }
                function do_insert() {
                  let d = tbody.thin_rowdata;
                  console.log(d);
                  validate({
                    container: tr,
                    valid: function () {
                      // console.log({ e, d });
                      d.push({ ...e.new_data, ...e.org_data });
                      thin(tbody).empty();
                      row_group(tbody, d);
                    },
                    invalid: function () {
                      e.done();
                    },
                  });
                }

                // if (e.rerender) delete e.rerender; // tr已经失效，rerender已经不可用。
                template?.inserted?.(e);
              },
            });
          }
        }
      }
    }
    // 渲染foot
    if (mode === "edit" || template.rowinsert || hassummary()) {
      let tfoot = document.createElement("tfoot");
      table.appendChild(tfoot);

      // if (template.rowinsert && mode === "edit") {
      //   let tr = document.createElement("tr");
      //   tfoot.appendChild(tr);
      //   tr.thin_data = template.rowinsert_defaultvalue || {};
      //   row_render({
      //     tr,
      //     insert: true,
      //     tbody: tfoot,
      //   });
      // }

      // let tr = document.createElement("tr");
      // tfoot.appendChild(tr);
      // tr.thin_data = {};
      // let row_template = [];
      // template.gridview.forEach((col) => {
      //   row_template.push({ td: col.foot || "" });
      // });
      // thin_render(tr, row_template);
      // console.log(hassummary());
      if (hassummary() && typeof template.summarydatapath === "string") {
        // console.log("hi");
        let tr = document.createElement("tr");
        tfoot.appendChild(tr);
        tr.thin_data = datarover(tfoot, template.summarydatapath);
        for (let col of template.gridview) {
          if (col.summary !== undefined) {
            let value = datarover(tr, col.summary);
            if (value === undefined) {
            } else if (col.NumberFormat) {
              thin_render(tr, {
                td: new Intl.NumberFormat("en-US", col.NumberFormat).format(
                  value
                ),
                class: col.class,
              });
            } else if (col.DateTimeFormat) {
              value = value?.replace(/\//g, "-");
              value = new Date(`${value}`);

              thin_render(tr, {
                td: !isNaN(value.getTime())
                  ? new Intl.DateTimeFormat(col.DateTimeFormat).format(
                      Date.UTC(
                        value.getFullYear(),
                        value.getMonth(),
                        value.getDate(),
                        value.getHours(),
                        value.getMinutes(),
                        value.getSeconds(),
                        value.getMilliseconds()
                      )
                    )
                  : "",
                class: col.class,
              });
            } else
              thin_render(tr, { td: `[[${col.summary}]]`, class: col.class });
          } else {
            thin_render(tr, { td: "", class: col.class });
          }
        }
      }
    }

    function hassummary() {
      if (template.gridview)
        for (let col of template.gridview) {
          if (col.summary !== undefined) {
            return true;
          }
        }
      return false;
    }

    function hasfoot() {
      if (template.gridview)
        template.gridview.forEach((col) => {
          if (col.foot !== undefined) return true;
        });
      return false;
    }

    function savescrollpos() {
      let rerender_container = nearest_render(gridview);
      if (template.id) {
        rerender_container[`thin_gridview_${template.id}`] = {
          top: gridview.scrollTop,
          left: gridview.scrollLeft,
        };
      }
      // console.log({ rerender_container });
    }

    function restorescrollpos() {
      if (template.id) {
        let rerender_container = nearest_render(gridview);
        let pos = rerender_container[`thin_gridview_${template.id}`];
        // console.log({ pos });
        if (pos) {
          gridview.scrollTo(pos);
        }
      }
    }

    // // 计算高度
    // if (template.height === "auto") {
    //   let parent = gridview.offsetParent;
    //   console.log({
    //     parent,
    //     scrollheight: parent.scrollHeight,
    //     top: gridview.offsetTop,
    //     height: gridview.offsetHeight,
    //     bottom: parent.scrollHeight - gridview.offsetTop - gridview.offsetHeight,
    //   });
    //   override.height = `calc(100% - ${gridview.offsetTop}px)`;
    // }

    // 冻结位置
    thin("th.fixed,td.fixed", thead).each((node) => {
      node.style.cssText = `left:${node.offsetLeft}px`;
    });
    thin(
      "tbody th.fixed,tbody td.fixed,tfoot th.fixed,tfoot td.fixed",
      table
    ).each((node) => {
      node.style.cssText = `left:${node.offsetLeft - table.offsetLeft}px`;
    });

    restorescrollpos();
  }
}
